路由中间件之 AddQueuedCookiesToResponse
简介
[
'App\Http\Middleware\EncryptCookies',
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
'Illuminate\Session\Middleware\StartSession',
'Illuminate\View\Middleware\ShareErrorsFromSession',
'App\Http\Middleware\VerifyCsrfToken',
'Illuminate\Routing\Middleware\SubstituteBindings',
'App\Http\Middleware\RedirectIfAuthenticated',
]
如上,前面一章我们讲解了 EncryptCookies 路由中间件的作用。
这一章我们来看一下 AddQueuedCookiesToResponse 路由中间件的作用。
从字面上来看,不难看出,大概指从某个专门管理 Cookie 的队列服务中,取出 Cookie 加入到响应中。
Cookie 容器服务
所谓 Cookie 容器服务指提供 Cookie 管理功能的类。即:Illuminate\Cookie\CookieJar
。
此服务,主要有:
- 获取
Symfony\Component\HttpFoundation\Cookie
真实 Cookie 对象实例的方法 - 利用如下数组,实现 Cookie 列表数据的管理
Illuminate\Cookie\CookieJar
protected $queued = [];
AddQueuedCookiesToResponse 中间件
中间件核心方法 handle 方法如下所示:
public function handle($request, Closure $next)
{
// 从 Laravel 内层获取响应
$response = $next($request);
// 直接获取 queued 数组,循环将 Cookie 取出并附加到响应头中
foreach ($this->cookies->getQueuedCookies() as $cookie) {
$response->headers->setCookie($cookie);
}
// 将响应抛给外层
return $response;
}
问题一:$this->cookies
从哪里来的
<?php
namespace Illuminate\Cookie\Middleware;
use Closure;
// 重点在这,利用 特别篇5 的讲解方式,我们知道 CookieJar 实际指向的是 Illuminate\Cookie\CookieJar
use Illuminate\Contracts\Cookie\QueueingFactory as CookieJar;
class AddQueuedCookiesToResponse
{
// 声明存储 Cookie 容器服务的属性
protected $cookies;
// 标准 IoC/DI 操作
public function __construct(CookieJar $cookies)
{
$this->cookies = $cookies;
}
// ... 省略若干代码
}
由此得知,$this->cookies
指 Illuminate\Cookie\CookieJar
的实例。
问题二: getQueuedCookies 方法在哪?
接续问题一,我们很容易就知道 getQueuedCookies 方法在 Illuminate\Cookie\CookieJar
中
public function getQueuedCookies()
{
return $this->queued;
}
直接返回了 $this->queued
数组
问题三:$this->queued
如何被赋值的?
讲这个问题之前,我们先看一下官方文档的一段内容
此段内容的位置 ---> 传送门
我们来看最下面这两段代码
Cookie::queue(Cookie::make('name', 'value', $minutes));
Cookie::queue('name', 'value', $minutes);
其中 Cookie 是 'cookie'
单词标识的门面,最终指向的对象恰恰就是 Illuminate\Cookie\CookieJar
我们看一下它的 queue 方法
public function queue(...$parameters)
{
// 验证第一个参数是否属于 Symfony\Component\HttpFoundation\Cookie 的实例
if (head($parameters) instanceof Cookie) {
// 如果第一个参数是 Symfony\Component\HttpFoundation\Cookie 的实例,则取出赋值个 $cookie
$cookie = head($parameters);
} else {
// 如果第一个参数不是属于 Symfony\Component\HttpFoundation\Cookie 的实例,那么则根据这些参数调用 make 方法,获取 Symfony\Component\HttpFoundation\Cookie 的实例。
$cookie = call_user_func_array([$this, 'make'], $parameters);
}
// 核心!!!,以关联数组的形式存储 Cookie
$this->queued[$cookie->getName()] = $cookie;
}
看到了没,if 语句判断的两种情况正好是官方文档所示的两种操作。